package com.crimerank;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.crimerank.data.BusRoute;
import com.crimerank.data.ParcelableGeoPoint;
import com.google.android.maps.GeoPoint;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import android.text.format.Time;

public class RouteSchedule extends BaseActivity {

	Bundle loc;
	BusRoute obj = null;
	BusRoute selectedRoute;
	ArrayList<GeoPoint> busPos = new ArrayList<GeoPoint>();
	ArrayList<GeoPoint> points = new ArrayList<GeoPoint>();

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.routeschedule);

		// Available in the intent: loc, BusRoute, StopName.
		this.loc = getIntent().getExtras().getBundle("loc");
		this.obj = (BusRoute) getIntent().getSerializableExtra("BusRoute");

		TextView stopPredictionName = (TextView) findViewById(R.id.stopPredictionName);
		stopPredictionName.setText(getIntent().getStringExtra("StopName"));

		// Parse the stored schedule strings and display.
		StringBuilder text = new StringBuilder();
		text.append(obj.getRouteId() + ": " + obj.getDirectionText() + "\n");
		text.append(obj.getTripHeadsign() + '\n');
		text.append(getIntent().getStringExtra("stopId") + "\n");

		Time now = new Time();
		now.setToNow();

		Time t = new Time();
		for (String s : obj.getSchedule()) {
			t.parse3339(s);
			if (t.after(now)) {
				text.append(t.format("%l:%M %p") + "**\n");
			} else {
				text.append(t.format("%l:%M %p") + "\n");
			}
		}

		TextView textSchedule = (TextView) findViewById(R.id.textSchedule);
		textSchedule.setText(text);

	}

	public void onClick(View v) {
		switch (v.getId()) {
		case (R.id.imageMap):
			try {
				prepareMap();
			} catch (JSONException e) {
				e.printStackTrace();
				Toast toast = Toast.makeText(getApplicationContext(),
						"Route map not available.", Toast.LENGTH_SHORT);
				toast.show();
				return;
			}

			try {
				getCurrentBusPosition();
			} catch (JSONException e) {
				e.printStackTrace();
				Toast toast = Toast.makeText(getApplicationContext(),
						"Bus position not available.", Toast.LENGTH_SHORT);
				toast.show();
			}

			Intent myIntent = new Intent(v.getContext(), Map.class);

			// Send current location and the list of points in the route.
			myIntent.putExtra("loc", loc);
			points = selectedRoute.getRoute();
			ArrayList<ParcelableGeoPoint> pointsExtra = new ArrayList<ParcelableGeoPoint>();
			for (GeoPoint point : points) {
				pointsExtra.add(new ParcelableGeoPoint(point));
			}
			myIntent.putExtra("points", pointsExtra);

			// Also send the type of map, lat/lon spans and center point.
			myIntent.putExtra("mapType", "geoRoute");
			myIntent.putExtra("latSpan", selectedRoute.getLatSpan());
			myIntent.putExtra("lonSpan", selectedRoute.getLonSpan());
			myIntent.putExtra("latCenter", selectedRoute.getLatCenter());
			myIntent.putExtra("lonCenter", selectedRoute.getLonCenter());

			// Pass through the stop location.
			myIntent.putExtra("stopLoc", getIntent().getBundleExtra("stopLoc"));

			// Pass through the bus locations.

			ArrayList<ParcelableGeoPoint> busPosExtra = new ArrayList<ParcelableGeoPoint>();
			for (GeoPoint point : busPos) {
				busPosExtra.add(new ParcelableGeoPoint(point));
			}
			myIntent.putExtra("busPos", busPosExtra);

			startActivity(myIntent);
			break;
		case (R.id.imageHome):
			myIntent = new Intent(v.getContext(), Home.class);
			myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			startActivity(myIntent);
			break;
		}
	}

	private void getCurrentBusPosition() throws JSONException {
		try {
			String url = getResources().getString(R.string.URL_BUS_POSITION);
			String query = String.format("routeId=%s&api_key=%s",
					URLEncoder.encode(obj.getRouteId(), "UTF-8"),
					URLEncoder.encode("s2f5rag8pa5fz53mg2e7s4et", "UTF-8"));

			// Perform the HTTP request
			String result = doHttpRequest(url, query);

			// Process results and display list
			processJson2(result, obj.getDirectionNum());
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public void processJson2(String str, String dirNum) throws JSONException {
		// Loop thru JSON array and parse out bus position info.
		JSONObject jo = new JSONObject(str);
		JSONArray ja = jo.getJSONArray("BusPositions");

		ArrayList<Double> lats = new ArrayList<Double>();
		ArrayList<Double> lons = new ArrayList<Double>();

		for (int i = 0; i < ja.length(); ++i) {
			JSONObject tmp = (JSONObject) ja.get(i);
			if (tmp.getString("DirectionNum").equals(obj.getDirectionNum())) {
				Double lat = new Double(tmp.getString("Lat"));
				Double lon = new Double(tmp.getString("Lon"));
				lats.add(lat);
				lons.add(lon);
				Log.d("TRIP START TIME", tmp.getString("TripStartTime"));
				Log.d("DEVIATION", tmp.getString("Deviation"));
			}
		}

		for (int i = 0; i < lats.size(); ++i) {
			Double lat = lats.get(i) * 1E6;
			Double lon = lons.get(i) * 1E6;
			busPos.add(new GeoPoint(lat.intValue(), lon.intValue()));
		}
	}

	private void prepareMap() throws JSONException {
		try {
			String url = getResources().getString(
					R.string.URL_BUS_ROUTE_DETAILS);
			String query = String.format("routeId=%s&api_key=%s",
					URLEncoder.encode(obj.getRouteId(), "UTF-8"),
					URLEncoder.encode("s2f5rag8pa5fz53mg2e7s4et", "UTF-8"));

			// Perform the HTTP request
			String result = doHttpRequest(url, query);

			// Process results and display list
			selectedRoute = processJson(result, obj.getDirectionNum());
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public BusRoute processJson(String str, String dirNum) throws JSONException {

		// Loop thru JSON array and parse out bus stop info.
		JSONObject jo = new JSONObject(str);
		jo = jo.getJSONObject("Direction" + dirNum);

		BusRoute busRoute = new BusRoute();
		busRoute.setDirectionNum(jo.getString("DirectionNum"));
		busRoute.setDirectionText(jo.getString("DirectionText"));
		busRoute.setTripHeadsign(jo.getString("TripHeadsign"));

		// Get the full shape of the route.
		JSONArray ja = jo.getJSONArray("Shape");

		// Process the first point in the route.
		JSONObject tmp = (JSONObject) ja.get(0);

		// Store the initial values of lat and lon for finding the min and max
		// during the loop.
		Double lat = 1E6 * Double.parseDouble(tmp.getString("Lat"));
		Double lon = 1E6 * Double.parseDouble(tmp.getString("Lon"));
		int minLat = lat.intValue();
		int maxLat = lat.intValue();
		int minLon = lon.intValue();
		int maxLon = lon.intValue();

		// Instantiate the list of points and add the first point.
		ArrayList<GeoPoint> route = new ArrayList<GeoPoint>();
		GeoPoint point = new GeoPoint(lat.intValue(), lon.intValue());
		route.add(point);

		// Loop through the remaining points, adding them to the route.
		// Note, the step size can be increased for faster results.
		for (int i = 1; i < ja.length(); i += 4) {
			tmp = (JSONObject) ja.get(i);

			lat = 1E6 * Double.parseDouble(tmp.getString("Lat"));
			lon = 1E6 * Double.parseDouble(tmp.getString("Lon"));
			// Integer seqNum = Integer.parseInt(tmp.getString("SeqNum"));

			// Check to see if the point has a min or max lat or lon.
			int tmpLat = lat.intValue();
			int tmpLon = lon.intValue();
			if (tmpLat < minLat)
				minLat = tmpLat;
			if (tmpLat > maxLat)
				maxLat = tmpLat;
			if (tmpLon < minLon)
				minLon = tmpLon;
			if (tmpLon > maxLon)
				maxLon = tmpLon;

			point = new GeoPoint(tmpLat, tmpLon);
			route.add(point);
		}

		// Store the full set of points composing the bus route.
		busRoute.setRoute(route);

		// Store the span of lat and lon.
		busRoute.setLatSpan(maxLat - minLat);
		busRoute.setLonSpan(maxLon - minLon);

		// Store the "center point" of the route display.
		Double centerLat = (maxLat + minLat) / 2.0;
		Double centerLon = (maxLon + minLon) / 2.0;
		busRoute.setCenter(centerLat.intValue(), centerLon.intValue());

		return busRoute;

	}

}
